﻿using System;
using UnityEngine;

// Token: 0x02000139 RID: 313
[DisallowMultipleComponent]
[AddComponentMenu("RVP/C#/Hover/Hover Wheel", 1)]
public class HoverWheel : MonoBehaviour
{
	// Token: 0x060005B1 RID: 1457 RVA: 0x0002CF44 File Offset: 0x0002B144
	private void Start()
	{
		this.tr = base.transform;
		this.rb = (Rigidbody)F.GetTopmostParentComponent<Rigidbody>(this.tr);
		this.vp = (VehicleParent)F.GetTopmostParentComponent<VehicleParent>(this.tr);
		this.flippedSideFactor = (float)((Vector3.Dot(this.tr.forward, this.vp.transform.right) >= 0f) ? -1 : 1);
		this.canDetach = (this.detachForce < float.PositiveInfinity && Application.isPlaying);
		this.bufferDistance = Mathf.Min(this.hoverDistance, this.bufferDistance);
		if (this.canDetach)
		{
			this.detachedWheel = new GameObject(this.vp.transform.name + "'s Detached Wheel");
			this.detachedWheel.layer = LayerMask.NameToLayer("Detachable Part");
			this.detachFilter = this.detachedWheel.AddComponent<MeshFilter>();
			this.detachFilter.sharedMesh = this.visualWheel.GetComponent<MeshFilter>().sharedMesh;
			MeshRenderer meshRenderer = this.detachedWheel.AddComponent<MeshRenderer>();
			meshRenderer.sharedMaterial = this.visualWheel.GetComponent<MeshRenderer>().sharedMaterial;
			this.detachedCol = this.detachedWheel.AddComponent<MeshCollider>();
			this.detachedCol.convex = true;
			this.detachedBody = this.detachedWheel.AddComponent<Rigidbody>();
			this.detachedBody.mass = this.mass;
			this.detachedWheel.SetActive(false);
		}
	}

	// Token: 0x060005B2 RID: 1458 RVA: 0x0002D0D4 File Offset: 0x0002B2D4
	private void Update()
	{
		if (this.visualWheel && this.connected)
		{
			this.TiltWheel();
		}
	}

	// Token: 0x060005B3 RID: 1459 RVA: 0x0002D0F8 File Offset: 0x0002B2F8
	private void FixedUpdate()
	{
		this.upDir = this.tr.up;
		if (this.getContact)
		{
			this.GetWheelContact();
		}
		else if (this.grounded)
		{
			this.contactPoint.point += this.rb.GetPointVelocity(this.tr.position) * Time.fixedDeltaTime;
		}
		this.compression = Mathf.Clamp01(this.contactPoint.distance / this.hoverDistance);
		if (this.grounded && this.doFloat && this.connected)
		{
			this.ApplyFloat();
			this.ApplyFloatDrive();
		}
	}

	// Token: 0x060005B4 RID: 1460 RVA: 0x0002D1B8 File Offset: 0x0002B3B8
	private void GetWheelContact()
	{
		RaycastHit raycastHit = default(RaycastHit);
		Vector3 pointVelocity = this.rb.GetPointVelocity(this.tr.position);
		RaycastHit[] array = Physics.RaycastAll(this.tr.position, -this.upDir, this.hoverDistance, GlobalControl.wheelCastMaskStatic);
		bool flag = false;
		float num = float.PositiveInfinity;
		foreach (RaycastHit raycastHit2 in array)
		{
			if (!raycastHit2.transform.IsChildOf(this.vp.tr) && raycastHit2.distance < num)
			{
				raycastHit = raycastHit2;
				num = raycastHit2.distance;
				flag = true;
			}
		}
		if (flag)
		{
			if (!raycastHit.collider.transform.IsChildOf(this.vp.tr))
			{
				this.grounded = true;
				this.contactPoint.distance = raycastHit.distance;
				this.contactPoint.point = raycastHit.point + pointVelocity * Time.fixedDeltaTime;
				this.contactPoint.grounded = true;
				this.contactPoint.normal = raycastHit.normal;
				this.contactPoint.relativeVelocity = this.tr.InverseTransformDirection(pointVelocity);
				this.contactPoint.col = raycastHit.collider;
			}
		}
		else
		{
			this.grounded = false;
			this.contactPoint.distance = this.hoverDistance;
			this.contactPoint.point = Vector3.zero;
			this.contactPoint.grounded = false;
			this.contactPoint.normal = this.upDir;
			this.contactPoint.relativeVelocity = Vector3.zero;
			this.contactPoint.col = null;
		}
	}

	// Token: 0x060005B5 RID: 1461 RVA: 0x0002D38C File Offset: 0x0002B58C
	private void ApplyFloat()
	{
		if (this.grounded)
		{
			float z = this.vp.norm.InverseTransformDirection(this.rb.GetPointVelocity(this.tr.position)).z;
			this.rb.AddForceAtPosition(this.upDir * this.floatForce * (Mathf.Pow(this.floatForceCurve.Evaluate(1f - this.compression), Mathf.Max(1f, this.floatExponent)) - this.floatDampening * Mathf.Clamp(z, -1f, 1f)), this.tr.position, ForceMode.Acceleration);
			if (this.contactPoint.distance < this.bufferDistance)
			{
				this.rb.AddForceAtPosition(-this.upDir * this.bufferFloatForce * this.floatForceCurve.Evaluate(this.contactPoint.distance / this.bufferDistance) * Mathf.Clamp(z, -1f, 0f), this.tr.position, ForceMode.Acceleration);
			}
		}
	}

	// Token: 0x060005B6 RID: 1462 RVA: 0x0002D4C0 File Offset: 0x0002B6C0
	private void ApplyFloatDrive()
	{
		float num = ((this.vp.localVelocity.z <= 0f) ? Mathf.Clamp01(this.vp.accelInput) : this.vp.brakeInput) * this.brakeForce + this.vp.ebrakeInput * this.ebrakeForce;
		this.rb.AddForceAtPosition(this.tr.TransformDirection((Mathf.Clamp(this.targetSpeed, -1f, 1f) * this.targetForce - num * Mathf.Max(5f, Mathf.Abs(this.contactPoint.relativeVelocity.x)) * Mathf.Sign(this.contactPoint.relativeVelocity.x) * this.flippedSideFactor) * this.flippedSideFactor, 0f, -this.steerRate * this.steerFactor * this.flippedSideFactor - this.contactPoint.relativeVelocity.z * this.sideFriction) * (1f - this.compression), this.tr.position, ForceMode.Acceleration);
	}

	// Token: 0x060005B7 RID: 1463 RVA: 0x0002D5EC File Offset: 0x0002B7EC
	private void TiltWheel()
	{
		float num = Mathf.Clamp(-this.steerRate * this.steerFactor * this.flippedSideFactor - Mathf.Clamp(this.contactPoint.relativeVelocity.z * 0.1f, -1f, 1f) * this.sideFriction, -1f, 1f);
		float num2 = ((this.vp.localVelocity.z <= 0f) ? Mathf.Clamp01(this.vp.accelInput) : this.vp.brakeInput) * this.brakeForce + this.vp.ebrakeInput * this.ebrakeForce;
		float num3 = Mathf.Clamp((Mathf.Clamp(this.targetSpeed, -1f, 1f) * this.targetForce - num2 * Mathf.Clamp(this.contactPoint.relativeVelocity.x * 0.1f, -1f, 1f) * this.flippedSideFactor) * this.flippedSideFactor, -1f, 1f);
		Transform transform = this.visualWheel;
		Quaternion localRotation = this.visualWheel.localRotation;
		Vector3 vector = new Vector3(-num3 * this.visualTiltAmount, -1f + Mathf.Abs(F.MaxAbs(new float[]
		{
			num,
			num3
		})) * this.visualTiltAmount, -num * this.visualTiltAmount);
		transform.localRotation = Quaternion.Lerp(localRotation, Quaternion.LookRotation(vector.normalized, Vector3.forward), this.visualTiltRate * Time.deltaTime);
	}

	// Token: 0x060005B8 RID: 1464 RVA: 0x0002D778 File Offset: 0x0002B978
	public void Detach()
	{
		if (this.connected && this.canDetach)
		{
			this.connected = false;
			this.detachedWheel.SetActive(true);
			this.detachedWheel.transform.position = this.visualWheel.position;
			this.detachedWheel.transform.rotation = this.visualWheel.rotation;
			this.detachedCol.sharedMaterial = this.detachedWheelMaterial;
			this.detachedCol.sharedMesh = ((!this.wheelMeshLoose) ? this.detachFilter.sharedMesh : this.wheelMeshLoose);
			this.rb.mass -= this.mass;
			this.detachedBody.velocity = this.rb.GetPointVelocity(this.visualWheel.position);
			this.detachedBody.angularVelocity = this.rb.angularVelocity;
			this.visualWheel.gameObject.SetActive(false);
		}
	}

	// Token: 0x060005B9 RID: 1465 RVA: 0x0002D888 File Offset: 0x0002BA88
	public void Reattach()
	{
		if (!this.connected)
		{
			this.connected = true;
			this.detachedWheel.SetActive(false);
			this.rb.mass += this.mass;
			this.visualWheel.gameObject.SetActive(true);
		}
	}

	// Token: 0x060005BA RID: 1466 RVA: 0x0002D8DC File Offset: 0x0002BADC
	private void OnDrawGizmosSelected()
	{
		this.tr = base.transform;
		Gizmos.color = Color.white;
		Gizmos.DrawRay(this.tr.position, -this.tr.up * this.hoverDistance);
		Gizmos.color = Color.red;
		Gizmos.DrawRay(this.tr.position, -this.tr.up * this.bufferDistance);
	}

	// Token: 0x060005BB RID: 1467 RVA: 0x0002D95F File Offset: 0x0002BB5F
	private void OnDestroy()
	{
		if (this.detachedWheel)
		{
			UnityEngine.Object.Destroy(this.detachedWheel);
		}
	}

	// Token: 0x04000827 RID: 2087
	private Transform tr;

	// Token: 0x04000828 RID: 2088
	private Rigidbody rb;

	// Token: 0x04000829 RID: 2089
	private VehicleParent vp;

	// Token: 0x0400082A RID: 2090
	[NonSerialized]
	public HoverContact contactPoint = new HoverContact();

	// Token: 0x0400082B RID: 2091
	[NonSerialized]
	public bool getContact = true;

	// Token: 0x0400082C RID: 2092
	[NonSerialized]
	public bool grounded;

	// Token: 0x0400082D RID: 2093
	public float hoverDistance;

	// Token: 0x0400082E RID: 2094
	[Tooltip("If the distance to the ground is less than this, extra hovering force will be applied based on the buffer float force")]
	public float bufferDistance;

	// Token: 0x0400082F RID: 2095
	private Vector3 upDir;

	// Token: 0x04000830 RID: 2096
	[NonSerialized]
	public bool doFloat;

	// Token: 0x04000831 RID: 2097
	public float floatForce = 1f;

	// Token: 0x04000832 RID: 2098
	public float bufferFloatForce = 2f;

	// Token: 0x04000833 RID: 2099
	[Tooltip("Strength of the suspension depending on how compressed it is, x-axis = compression, y-axis = force")]
	public AnimationCurve floatForceCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f);

	// Token: 0x04000834 RID: 2100
	public float floatExponent = 1f;

	// Token: 0x04000835 RID: 2101
	public float floatDampening;

	// Token: 0x04000836 RID: 2102
	private float compression;

	// Token: 0x04000837 RID: 2103
	[NonSerialized]
	public float targetSpeed;

	// Token: 0x04000838 RID: 2104
	[NonSerialized]
	public float targetForce;

	// Token: 0x04000839 RID: 2105
	private float flippedSideFactor;

	// Token: 0x0400083A RID: 2106
	public float brakeForce = 1f;

	// Token: 0x0400083B RID: 2107
	public float ebrakeForce = 2f;

	// Token: 0x0400083C RID: 2108
	[NonSerialized]
	public float steerRate;

	// Token: 0x0400083D RID: 2109
	[Tooltip("How much the wheel steers")]
	public float steerFactor;

	// Token: 0x0400083E RID: 2110
	public float sideFriction;

	// Token: 0x0400083F RID: 2111
	[Header("Visual Wheel")]
	public Transform visualWheel;

	// Token: 0x04000840 RID: 2112
	public float visualTiltRate = 10f;

	// Token: 0x04000841 RID: 2113
	public float visualTiltAmount = 0.5f;

	// Token: 0x04000842 RID: 2114
	private GameObject detachedWheel;

	// Token: 0x04000843 RID: 2115
	private MeshCollider detachedCol;

	// Token: 0x04000844 RID: 2116
	private Rigidbody detachedBody;

	// Token: 0x04000845 RID: 2117
	private MeshFilter detachFilter;

	// Token: 0x04000846 RID: 2118
	[Header("Damage")]
	public float detachForce = float.PositiveInfinity;

	// Token: 0x04000847 RID: 2119
	public float mass = 0.05f;

	// Token: 0x04000848 RID: 2120
	[NonSerialized]
	public bool connected = true;

	// Token: 0x04000849 RID: 2121
	[NonSerialized]
	public bool canDetach;

	// Token: 0x0400084A RID: 2122
	public Mesh wheelMeshLoose;

	// Token: 0x0400084B RID: 2123
	public PhysicMaterial detachedWheelMaterial;
}
